$avatar_column_width: 46px;
$distance_of_text_elements_from_message_box_top: 8.5px;
$distance_of_non_text_elements_from_message_box: 6px;
$message_box_margin: 3px;

/* The time column usually just needs enough space to display the
   timestamp. The minimum width here is enough for "22:22 PM", which
   is roughly the widest this will be in English; this is nice as the
   timestamps and message controls will be vertically aligned.

   But in some locales, the time encoding is wider, (especially where
   the "PM" abbreviation is longer), so we allow the column to be
   wider for individual messages if required, up to `max-content`, to
   prevent ugly line-wrapping. In practice, it's unlikely we'll see
   anything wider than 60px. */
$time_column_min_width: 42px; /* + padding */

.message_row {
    display: grid;
    /* Prevent the messagebox column from overflowing the 1fr
       space allotted by specifying `minmax(0,1fr)`, which
       sets 0 as the minimum size, not the grid default of
       `auto`. */
    grid-template: auto auto / 2px minmax(0, 1fr);
    grid-template-areas:
        "date_unread_marker    date_row  "
        "message_unread_marker messagebox";

    border-left: 1px solid var(--color-message-list-border);
    border-right: 1px solid var(--color-message-list-border);
    background-color: var(--color-background-stream-message-content);

    &.direct_mention {
        background-color: var(--color-background-direct-mention);
    }

    &.group_mention {
        background-color: var(--color-background-group-mention);
    }

    .date_row {
        grid-area: date_row;
        /* We only want padding for the date rows between recipient blocks */
        padding-bottom: 0;

        & span {
            font-size: calc(12em / 14);
            font-style: normal;
            font-weight: 600;
            line-height: 17px; /* identical to box height, or 131% */
            text-align: right;
            letter-spacing: 0.04em;
            color: var(--color-date);
            /* Right padding matches time in message row and date in recipient row. */
            padding: 8px 6px 8px 4px;
        }
    }

    .unread_marker {
        margin-left: var(--unread-marker-left);
        opacity: 0;
        transition: all 0.3s ease-out;

        &.slow_fade {
            transition: all 2s ease-out;
        }

        &.fast_fade {
            transition: all 0.3s ease-out;
        }

        &.date_unread_marker {
            grid-area: date_unread_marker;

            .unread-marker-fill {
                border-radius: 0 !important;
                height: 100% !important;
            }
        }

        &.message_unread_marker {
            grid-area: message_unread_marker;
        }
    }

    .unread-marker-fill {
        height: 100%;
        width: 2px;
        background: linear-gradient(
            90deg,
            var(--color-unread-marker) 30%,
            hsl(217deg 64% 59% / 0%)
        );
    }

    &.unread .unread_marker {
        transition: all 0.3s ease-out;
        opacity: 1;
    }

    .messagebox {
        grid-area: messagebox;
        word-wrap: break-word;
        cursor: pointer;
        border: none;
        /* The left padding value accounts for a 2px
          unread marker, ensuring a uniform 5px of
          padding on either side of the message box. */
        padding: 0 5px 0 3px;

        &:hover .message_controls,
        &:hover .message_failed {
            .empty-star:hover {
                cursor: pointer;
            }

            > div {
                opacity: 1;
                visibility: visible;
            }
        }
    }

    .messagebox .messagebox-content {
        display: grid;
        align-items: baseline;
        padding-left: 10px;
        /* Prevent the message column from overflowing the 1fr
           space allotted by specifying `minmax(0,1fr)`, which
           sets 0 as the minimum size, not the grid default of
           `auto`. */
        grid-template:
            var(--message-box-icon-height) repeat(3, auto) /
            $avatar_column_width minmax(0, 1fr) calc(
                3 * var(--message-box-icon-width)
            )
            8px minmax($time_column_min_width, max-content);
        /* Named grid areas provide flexibility for positioning grid items
           reliably, even if the row or column definitions of the grid change. */
        grid-template-areas:
            "edited message   controls . time"
            ".      message   .        . .   "
            ".      more      .        . .   "
            ".      reactions .        . .   ";

        &.content_edit_mode {
            cursor: default;
            /* Set the controls area to 0 to give more space
               to the edit/source view area. */
            grid-template-columns: $avatar_column_width minmax(0, 1fr) 0 8px minmax(
                    $time_column_min_width,
                    max-content
                );
        }

        @media (width < $sm_min), ((width >= $md_min) and (width < $mc_min)) {
            grid-template-columns:
                $avatar_column_width minmax(0, 1fr) calc(
                    2 * var(--message-box-icon-width)
                )
                8px minmax($time_column_min_width, max-content);
        }

        .message_controls {
            grid-area: controls;

            @media (width < $sm_min),
                ((width >= $md_min) and (width < $mc_min)) {
                /* This is intended to target the first message_controls child
                   when there are 3 displayed. 4 = 3 + hidden message_failed element. */
                .message_control_button:nth-last-child(4) {
                    display: none;
                }
            }
        }

        .message_edit_notice {
            grid-area: edited;
        }

        .message_time {
            justify-self: end;
            padding-right: 5px;
            /* Maintain first-line baseline regardless of
               what happens in the message-content area (e.g., a
               collapsed message, or source/edit view). This
               line-height also keeps EDITED/MOVED messages
               in place, care of their baseline-group participation
               within the grid.

               That said, 28px is a bit of a magical number.
               In theory, this should be 27px. That's the height
               of a single-message row without a sender. (See the
               calculations for the height of a single-line,
               sender-less message row in the message box grid.)
               But when shifting into collapsed or source views,
               28px is necessary to maintain the vertical alignment
               of the EDITED messages, hover controls, and
               timestamp. It's possible that this is also due to a
               a rounding error, given how --message-box-line-height
               is expressed as a unitless decimal. */
            line-height: 28px;
            text-align: end;
            grid-area: time;

            &.notvisible {
                /* This happens when message failed to send. We don't want to
                   display time but still want it to occupy space. */
                width: 45px !important;
                position: unset !important;
            }
        }

        .slow-send-spinner {
            display: none;
            justify-self: end;
            margin-right: 10px;
            text-align: end;
            grid-area: time;
        }

        .message_content {
            grid-area: message;
            /*
            Space between two single line messages in a paragraph is 10px.
            There is 3px margin above and below a message. So, having a 2px
            padding above and below the message will make the space between
            all single paragraphs the same.
            */
            padding: 2px 0;
            color: var(--color-text-message-default);
            line-height: var(--message-box-line-height);
            min-height: 17px;
            display: block;
            position: relative;
            overflow: hidden;

            &:empty {
                display: none;
            }

            &.condensed {
                max-height: 8.5em;
                min-height: 0;
                overflow: hidden;
                mask-image: linear-gradient(
                    to top,
                    hsl(0deg 0% 100% / 0%) 0%,
                    hsl(0deg 0% 100%) 60px
                );
                mask-size: cover;
            }

            &.collapsed {
                padding: 0;
                max-height: 0;
                min-height: 0;
                overflow: hidden;
            }
        }

        .message_reactions {
            grid-area: reactions;
            display: flex;
            /* Allow reactions to wrap in mobile viewports */
            flex-wrap: wrap;
            /* Keep reactions aligned to start (top), so that the
               margin on the reaction button doesn't appear to
               stretch the reactions taller. */
            align-items: flex-start;
            /* Control reaction spacing with a gap */
            gap: 4px;
        }

        .message_edit {
            grid-area: message;
            /* Align self to start, rather than baseline, so the baseline
              is preserved from the message itself--keeping the time,
              edit message, and controls at the same vertical alignment. */
            align-self: start;
            margin-top: $distance_of_non_text_elements_from_message_box;
        }

        .message_length_controller {
            grid-area: more;
        }

        .collapsed ~ .message_length_controller {
            /* When content is collapsed, the length controller
               should occupy the space ordinarily assigned to
               the message. */
            grid-area: message;
            /* However, don't let the SHOW MORE button participate
               in the baseline group. */
            align-self: start;

            .message_length_toggle {
                /* Ensure that a collapsed message maintains the
                   same space around the toggle button as any other
                   message-row content. */
                margin: 4px 0;
            }
        }

        &.content_edit_mode .message_length_controller {
            /* If entering edit mode on a collapsed message,
               just hide the controller area. This preserves
               the collapsed state of the message, which need
               not be touched. We just need to hide the button.
               This works for condensed messages, too. */
            display: none;
        }
    }

    &.include-sender {
        .messagebox .messagebox-content {
            grid-template-areas:
                "avatar sender    controls . time"
                "avatar message   .        . .   "
                ".      more      .        . .   "
                ".      reactions .        . .   ";

            .message_edit {
                /* No top margin when there's a sender row */
                margin-top: 0;
            }

            &.is-me-message {
                grid-template-areas:
                    "avatar sender    controls . time"
                    "avatar sender    .        . .   "
                    ".      more      .        . .   "
                    ".      reactions .        . .   ";

                .message-avatar {
                    /* Set the line-height to match the height of the avatar image
                       to center me-messages within the baseline group. */
                    line-height: var(--message-box-avatar-height);
                    align-self: baseline;
                }

                .message_sender {
                    /* Don't display message sender as flexbox for me-messages. */
                    display: block;
                    /* This preserves a consistent bottom spacing on the me-message
                       grid, which ordinarily benefits from the margin of <p>
                       elements in the markdown--which single-line me-messages do
                       not receive.

                       It also ensures a uniform space-relationship between the top: of the avatar and the top of the sender_name line.

                       However, this should all arguably be handled from the grid
                       container or the grid definition itself. */
                    margin: $message_box_margin 0;

                    /* Set the same line-height as on message content for
                       me-messages. */
                    line-height: var(--message-box-line-height);

                    /* Display message components inline, with wrapping white-space,
                       so the sender name and message display as a continuous line
                       of wrapping text. */
                    .sender_name {
                        white-space: normal;
                        display: inline;
                    }

                    .sender_name_text {
                        max-width: 100%;
                    }
                }

                &.content_edit_mode {
                    .message_sender {
                        /* Keep the me-message participating in the baseline */
                        visibility: hidden;
                    }

                    .message_edit {
                        /* Use the sender grid area for the me-message edit/view-source box */
                        grid-area: sender;
                        margin-top: $distance_of_non_text_elements_from_message_box;
                    }
                }
            }

            .message-avatar {
                grid-area: avatar;
                /* The picture should not participate in the baseline group. */
                align-self: start;
                /* Because the avatar may be the tallest element in a
                  single-line me message, this margin preserves the
                  overall height of the message box. */
                margin: $distance_of_non_text_elements_from_message_box 0;
            }

            .status-message {
                font-weight: normal;
            }

            .message_content {
                padding-top: 0;
                grid-area: message;
            }

            .message_time {
                grid-area: time;
                /* Don't adjust the line-height for collapsed or
                   edited/source messages when there's a sender,
                   as the sender text is always visible. */
                line-height: inherit;
            }

            .slow-send-spinner {
                align-self: center;
                position: unset;
                margin-top: 1px;
            }

            .message_edit_notice {
                /* When the edit notice is inline, as on edited me-messages,
                  the inline-block and accompanying vertical-align styles will
                  apply */
                display: inline-block;
                vertical-align: baseline;
                /* A bit of margin here helps these not look associated with the name. */
                margin-left: 4px;
            }

            .message_sender {
                overflow: hidden;
                text-overflow: ellipsis;
                grid-area: sender;
                display: flex;
                /* Ensure flexed sender info (name, status emoji, inline EDITED)
                   forms a baseline group, which will participate with the
                   message-box grid's baseline group, too. */
                align-items: baseline;

                margin-top: $message_box_margin;

                .zulip-icon.zulip-icon-bot {
                    align-self: center;
                    padding: 0 0 0 5px;
                }

                .sender_name {
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    /* It is important to use line-height `normal` here since user's name can
                       be in any language and `line-height: 1` doesn't work to accommodate text
                       from start and end vertically in all languages. */
                    line-height: normal;
                    outline: none;
                    align-self: baseline;
                }
            }
        }
    }

    /* Locally echoed messages. */
    &.locally-echoed .message_time {
        opacity: 0;
        /* Don't show pointer when message_time doesn't has a link. */
        cursor: default;
    }

    /* Show the spinner only for messages that are still locally echoed. */
    &.locally-echoed .slow-send-spinner {
        display: unset !important;
        cursor: default;
    }

    /* Message-editing styles */
    .message-edit-buttons-and-timer {
        margin-top: 5px;
        display: flex;
        gap: 5px;
        /* Allow items to occupy full height.
           This is especially important for
           buttons that are flex items. */
        align-items: stretch;
    }

    .message-actions-button {
        box-sizing: border-box;
        /* Display the actions buttons as
           flex containers for positioning
           text and spinners. */
        display: flex;
        align-items: center;
        justify-content: center;
        height: 28px;
        padding: 0 10px;
        border-radius: 4px;
        border: 0;
        line-height: 1;
    }

    .message_edit_save {
        /* Match Save button's basic colors to
           the compose box Send button. */
        color: var(--color-compose-send-button-icon-color);
        background-color: var(--color-compose-send-button-background);

        &:hover {
            background-color: var(
                --color-compose-send-button-background-interactive
            );
        }

        &:disabled {
            /* Replicate the `.new-style` disabled values,
               without any color shifts. */
            cursor: not-allowed;
            filter: saturate(0);
            opacity: 0.5;
        }
    }

    .message_edit_cancel,
    .message_edit_close {
        color: var(--color-exit-button-text);
        background: var(--color-exit-button-background);
        border: 1px solid var(--color-exit-button-border);

        &:hover {
            background: var(--color-exit-button-background-interactive);
        }
    }
}

/* Additional message-editing UI styles. */

.message_edit_content {
    line-height: 18px;
    resize: vertical !important;
    max-height: 24em;
}

.message_edit_countdown_timer {
    text-align: right;
    display: inline;
    color: hsl(0deg 0% 63%);

    &.expired {
        color: hsl(4deg 58% 33%);
    }
}

.message-edit-timer {
    display: none;
    /* Center vertically relative to
       buttons. */
    align-self: center;
    /* Use flexbox to position to far right of
       the Save and Cancel buttons. */
    margin-left: auto;
}

.message-edit-feature-group {
    display: flex;
    margin: 0;
    align-items: baseline;
}

.message_edit_save .loader {
    display: none;
    height: 28px;
    width: 28px;
}

.edit-controls {
    .btn-wrapper {
        cursor: not-allowed;
    }

    .disable-btn {
        pointer-events: none;
    }
}

.message_edit_spinner {
    margin-right: 8px;
    padding-top: 5px;
}

.message_edit_spinner .loading_indicator_spinner {
    width: 20px;
    height: 20px;
}

.message_edit {
    display: none;
}

/* Reduce some of the heavy padding from Bootstrap. */
.message_edit_form {
    margin-bottom: 10px;
    cursor: default;

    .edit-controls {
        margin-left: 0;
        margin-top: 0;
    }

    /* Override the default border-radius to properly align
       the button corners with `stream_header_colorblock`. */
    .dropdown-toggle {
        border-radius: 1px 4px 4px 1px !important;
    }

    .dropdown-list-widget,
    .stream_header_colorblock {
        margin-bottom: 10px;
    }

    & textarea {
        width: 100%;
        min-width: 206px;
        box-sizing: border-box;
        /* Setting resize as none hides the bottom right diagonal box
           (which even has a background color of its own!). */
        resize: none !important;
        color: hsl(0deg 0% 33%);
        background-color: hsl(0deg 0% 100%);
        border-radius: 4px;
        vertical-align: middle;
        border: 1px solid hsl(0deg 0% 80%);
        padding: 4px 6px;
        margin-bottom: 10px;

        box-shadow: inset 0 1px 1px hsl(0deg 0% 0% / 7.5%);
        transition:
            border linear 0.2s,
            box-shadow linear 0.2s;

        &:focus {
            border-color: hsl(206.5deg 80% 62% / 80%);
            outline: 0;

            box-shadow:
                inset 0 1px 1px hsl(0deg 0% 0% / 7.5%),
                0 0 8px hsl(206.5deg 80% 62% / 60%);
        }

        &:read-only,
        &:disabled {
            cursor: not-allowed;
            background-color: hsl(0deg 0% 93%);
        }
    }
}

.message_edit_notice {
    font-size: 10px;
    opacity: 0.5;
    user-select: none;
    white-space: nowrap;
    overflow-x: hidden;
    overflow-x: clip;
}

.fade-in-message {
    animation-name: fadeInMessage;
    animation-duration: 1s;
    animation-iteration-count: 1;

    .message_edit_notice {
        animation-name: fadeInEditNotice;
        animation-duration: 1s;
        animation-iteration-count: 1;
    }
}

.message_edit_notice_hover:hover {
    opacity: 1;
}

.recipient_row {
    /* See https://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class/8539107#8539107
       for details on how this works */
    .message_row.unread {
        .date_unread_marker {
            display: none;
        }
    }

    /* Select all but the first .message_row.unread,
       and remove the properties set from the previous rule. */
    .message_row.unread ~ .message_row.unread {
        .date_unread_marker {
            display: block;
        }
    }
}
